home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcr / pcr4_4.lha / DIST / gc / GCdirty.c < prev    next >
C/C++ Source or Header  |  1991-08-06  |  8KB  |  272 lines

  1. /* begincopyright
  2.   Copyright (c) 1988,1990 Xerox Corporation. All rights reserved.
  3.   Use and copying of this software and preparation of derivative works based
  4.   upon this software are permitted. Any distribution of this software or
  5.   derivative works must comply with all applicable United States export
  6.   control laws. This software is made available AS IS, and Xerox Corporation
  7.   makes no warranty about the software, its performance or its conformity to
  8.   any specification. Any person obtaining a copy of this software is requested
  9.   to send their name and post office or electronic mail address to:
  10.     PCR Coordinator
  11.     Xerox PARC
  12.     3333 Coyote Hill Rd.
  13.     Palo Alto, CA 94304
  14.     
  15.   Parts of this software were derived from code bearing the copyright notice:
  16.   
  17.   Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  18.   This material may be freely distributed, provided this notice is retained.
  19.   This material is provided as is, with no warranty expressed or implied.
  20.   Use at your own risk.
  21.   
  22.   endcopyright */
  23.  
  24. # include "xr/GCPrivate.h"
  25. # include "xr/GCVirtualDirty.h"
  26.  
  27. /* Boehm, May 15, 1990 2:00:28 pm PDT */
  28. /*
  29.  * contains:
  30.  *   GC_clear_dirty_bits()  -  reset all pages to clean.  Doesn't affect
  31.  *                   GC_dirty_bits array.
  32.  *   GC_set_dirty_bits() - Set all pages to dirty status. Doesn't affect
  33.  *                   GC_dirty_bits array.
  34.  *   GC_clear_some_dirty_bits(start,limit) - same, but only for a specified
  35.  *                         region of the heap.
  36.  *   GC_get_dirty_bits()  -  Set GC_dirty bits to reflect which blocks have
  37.  *                 been touched.
  38.  *   GC_get_and_clear_dirty_bits() - Set GC_dirty_bits and atomically
  39.  *                     reset pages to clean.
  40.  *   GC_propagate_dirty_bits() - propagate dirty bits to all blocks covered
  41.  *                 by large dirty objects.
  42.  *
  43.  *  Boehm, September 28, 1990 2:51:21 pm PDT
  44.  */
  45.  
  46. # if VD_PAGE_SIZE != HBLKSIZE
  47.      --> We assume VD_PAGE_SIZE == HBLKSIZE
  48. # endif 
  49.  
  50. /* Clear dirty bits for all pages in the specified range */
  51. void GC_clear_some_dirty_bits(start, limit)
  52. char * start;
  53. char * limit;
  54. {
  55. # ifdef DIRTY_BITS
  56.     struct XR_VDBufRep VDArgBuf;
  57.     int errno;
  58.     
  59.     /* Set up memory region descriptor */
  60.         VDArgBuf.vdb_buf = (char *) 0;  /* dirty bit table */
  61.         VDArgBuf.vdb_seg.seg_addr = (XR_Pointer)start;
  62.         VDArgBuf.vdb_seg.seg_bytes = limit - start;
  63.         
  64.     /* Issue the call */
  65.         errno = -XR_VDOp(XR_VDOpCodeSetClean, 1, &VDArgBuf);
  66.         if (errno > 0) {
  67.             GC_iprintf("Failed to clear dirty bits, errno = %d\n", errno);
  68.         }
  69. # endif
  70. }
  71.  
  72. /* Clear dirty bits for all entries in the heap and data segment */
  73. void GC_clear_dirty_bits()
  74. {
  75. # ifdef DIRTY_BITS
  76.     /* Make sure VD_base is initialized */
  77.         XR_StartVD();
  78.     GC_clear_some_dirty_bits(VD_base, GC_heaplim);
  79. # endif
  80. }
  81.  
  82. /* Set dirty bits for all pages in the heap and data segment */
  83. void GC_set_dirty_bits()
  84. {
  85. # ifdef DIRTY_BITS
  86.     struct XR_VDBufRep VDArgBuf;
  87.     int errno;
  88.     
  89.     /* Make sure VD_base is initialized */
  90.         XR_StartVD();
  91.     /* Set up memory region descriptor */
  92.         VDArgBuf.vdb_buf = (char *) 0;  /* dirty bit table */
  93.         VDArgBuf.vdb_seg.seg_addr = (XR_Pointer)VD_base;
  94.         VDArgBuf.vdb_seg.seg_bytes = GC_heaplim - VD_base;
  95.         
  96.     /* Issue the call */
  97.         errno = -XR_VDOp(XR_VDOpCodeSetDirty, 1, &VDArgBuf);
  98.         if (errno > 0) {
  99.             GC_iprintf("Failed to set dirty bits, errno = %d\n", errno);
  100.             GC_abort("Failed to set dirty bits\n");
  101.         }
  102. # endif
  103. }
  104.  
  105.     
  106. /* Set GC_dirty_bits array entries for each page.  */
  107. void GC_get_dirty_bits()
  108. {
  109.   register unsigned long limit;
  110.   register unsigned long index;
  111. # ifdef DIRTY_BITS
  112.     register unsigned long offset;
  113.     register struct hblk * h;
  114.     register word * p;
  115.     char map_entry;
  116.     struct XR_VDBufRep VDArgBuf;
  117.     int errno;
  118. #   ifdef PRINTSTATS
  119.       long n_clean = 0;
  120.       long n_dirty = 0;
  121. #   endif
  122.  
  123.     /* Make sure VD_base is initialized */
  124.         XR_StartVD();
  125.  
  126.     /* Set up memory region descriptor */
  127.         VDArgBuf.vdb_buf = (char *) GC_dirty_bits;  /* dirty bit table */
  128.         VDArgBuf.vdb_seg.seg_addr = (XR_Pointer)VD_base;
  129.         VDArgBuf.vdb_seg.seg_bytes = GC_heaplim - VD_base;
  130.         
  131.     /* Issue the call */
  132.         limit = divHBLKSZ(GC_heaplim - VD_base);
  133.         errno = -XR_VDOp(XR_VDOpCodeNOOP, 1, &VDArgBuf);
  134.         if (errno > 0) {
  135.             GC_iprintf("Failed to retrieve dirty bits, errno = %d\n", errno);
  136.             for (index = 0;
  137.                  index < limit; index++) {
  138.                  GC_dirty_bits[index] = 1;
  139.             }                 
  140.         }
  141.  
  142. #   ifdef PRINTSTATS
  143.     offset = divHBLKSZ(GC_heapstart - VD_base);
  144.         for(index = offset;
  145.             index < limit; index++) {
  146.             if (hblkmap[index-offset] != HBLK_INVALID) {
  147.               if (GC_dirty_bits[index]) {
  148.                 n_dirty++;
  149.               } else {
  150.                 n_clean++;
  151.               }
  152.             }
  153.         }
  154. #   endif
  155. #   ifdef PRINTSTATS
  156.        GC_printf("Found %d clean, %d dirty pages\n", n_clean, n_dirty);
  157. #   endif
  158. # else
  159.     /* Make sure VD_base is initialized */
  160.         XR_StartVD();
  161.     limit = divHBLKSZ(GC_heaplim - VD_base);    
  162.     for (index = 0;
  163.         index < limit; index++) {
  164.         GC_dirty_bits[index] = 1;
  165.     }
  166. # endif
  167. }
  168.     
  169. /* Set GC_dirty_bits array entries for each page and clear dirty bits.  */
  170. void GC_get_and_clear_dirty_bits()
  171. {
  172. # ifdef DIRTY_BITS
  173.     register struct hblk * h;
  174.     register word * p;
  175.     char map_entry;
  176.     register unsigned long index;
  177.     struct XR_VDBufRep VDArgBuf;
  178.     int errno;
  179. #   ifdef PRINTSTATS
  180.       register unsigned long offset;
  181.       long n_clean = 0;
  182.       long n_dirty = 0;
  183. #   endif
  184.     register unsigned long limit;
  185.  
  186.     /* Make sure VD_base is initialized */
  187.         XR_StartVD();
  188.  
  189.     /* Set up memory region descriptor */
  190.         VDArgBuf.vdb_buf = (char *) GC_dirty_bits;  /* dirty bit table */
  191.         VDArgBuf.vdb_seg.seg_addr = (XR_Pointer)VD_base;
  192.         VDArgBuf.vdb_seg.seg_bytes = GC_heaplim - VD_base;
  193.         
  194.     /* Issue the call */
  195.         limit = divHBLKSZ(GC_heaplim - VD_base);
  196.         errno = -XR_VDOp(XR_VDOpCodeSetClean, 1, &VDArgBuf);
  197.         if (errno > 0) {
  198.             GC_iprintf("Failed to retrieve dirty bits, errno = %d\n", errno);
  199.             for (index = 0;
  200.                  index < limit; index++) {
  201.                  GC_dirty_bits[index] = 1;
  202.             }                 
  203.         }
  204.  
  205. #   ifdef PRINTSTATS
  206.        offset = divHBLKSZ(GC_heapstart - VD_base);
  207.        for (index = offset;
  208.             index < limit; index++) {
  209.             if (hblkmap[index-offset] != HBLK_INVALID) {
  210.               if (GC_dirty_bits[index]) {
  211.                 n_dirty++;
  212.               } else {
  213.                 n_clean++;
  214.               }
  215.             }
  216.        }
  217. #   endif
  218. #   ifdef PRINTSTATS
  219.        GC_printf("Found %d clean, %d dirty pages - cleaned all\n",
  220.                   n_clean, n_dirty);
  221. #   endif
  222. # else
  223.     GC_get_dirty_bits();
  224. # endif
  225. }
  226.  
  227. /* Set dirty bit of first page of chunk if any of the continuation */
  228. /* pages are dirty, and if the page contains composite objects.    */
  229. void GC_propagate_dirty_bits()
  230. {
  231. # ifdef DIRTY_BITS
  232.     register long index = 0;
  233.     register long offset = divHBLKSZ(GC_heapstart - VD_base);
  234.     register char dirty;
  235.     register unsigned long limit = divHBLKSZ(GC_heaplim - GC_heapstart);
  236.  
  237.     dirty = 0;
  238.     for (index = limit - 1; index >= 0; index--) {
  239.     switch(hblkmap[index]) {
  240.         case HBLK_INVALID:
  241.             /* While we're chugging down the continuation pages,
  242.            we might get paused, and some other process might
  243.            set HBLK_INVALID.  For example, a large block might
  244.            be explicitly freed.
  245.            */
  246.             if (dirty && GC_running_exclusive) {
  247.                 GC_iprintf("Corrupted hblkmap (%d)\n", index);
  248.                 GC_abort("Corrupted hblkmap");
  249.             } else {
  250.             dirty = FALSE;
  251.         }
  252.         break;
  253.         case HBLK_VALID:
  254. #        ifdef SEPARATE_HEADERS
  255.               if (GC_headers[index] -> hbh_sz > 0) {
  256. #        else
  257.               if (hb_sz(GC_heapstart + HBLKSIZE * index) > 0) {
  258. #        endif
  259.                 /* Composite */
  260.             GC_dirty_bits[index + offset] |= dirty;
  261.         }
  262.         dirty = 0;
  263.         break;
  264.         default:
  265.         dirty |= GC_dirty_bits[index + offset];
  266.         break;
  267.     }
  268.     }
  269. # endif
  270. /* otherwise everything is "dirty" to start with */
  271. }
  272.